;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥;      
;♥ .      _ _  __   .                                               ♥;
;♥     * ( | )/_/       ; Computers Are Easy                        ♥;
;♥  . __( >O< )    *    ; Love is Kind v. 2.0                       ♥;
;♥    \_\(_|_)  +       ; Electronic Love Operation 2015            ♥;
;♥  +       .         .                                             ♥;
;♥                                                                  ♥;
;♥                      ; Playing the ROM: Press up and down to     ♥;
;♥                      ; change colors. Press B to toggle          ♥;
;♥                      ; glitching. Press A to toggle sparkle      ♥;
;♥                      ; animation.                                ♥;
;♥                                                                  ♥;
;♥                      ; This source code is fully commented.      ♥;
;♥                      ; Hopefully it is of help to those wishing  ♥;
;♥                      ; to know more about how NES code is        ♥;
;♥                      ; written. In the FCEUX emulator (Windows   ♥;
;♥                      ; only), you can watch variables update by  ♥;
;♥                      ; loading the compiled ROM and choosing     ♥;
;♥                      ; Debug > Hex editor. Watch values $0000    ♥;
;♥                      ; through $0015. To compile from source,    ♥;
;♥                      ; use NESASM3 (not included). NESASM3 usage ♥;
;♥                      ; is <filepath> nesasm3 loveiskind.asm      ♥;
;♥                                                                  ♥;
;♥                      ; This program was written in one day, on   ♥;
;♥                      ; the occasion of the US Supreme Court      ♥;
;♥                      ; ruling on marriage equality. Version 2.0  ♥;
;♥                      ; has additional code commenting, and the   ♥;
;♥                      ; sparkle animation was changed to sync     ♥;
;♥                      ; with the music. As this program was       ♥;
;♥                      ; written quickly, there likely remain      ♥;
;♥                      ; errors or opportunities to make the code  ♥;
;♥                      ; even more efficient. Perhaps you can find ♥;
;♥                      ; them. Have fun, traveler!                 ♥;
;♥                                                                  ♥;
;♥                      ; Rachel Simone Weil                        ♥;
;♥                      ; http://nobadmemories.com                  ♥;
;♥                      ; http://github.com/hxlnt                   ♥;
;♥                                                                  ♥;
;♥                                                                  ♥;
;♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥;

                    
                                                        
;;;;;;;; + 1.0 NESASM3.0 HEADER + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;      
                                                                    ;;
;;    .inesprg 2          ; 2 16-KB banks PRG data (32KB total)     ;;
;;    .ineschr 1          ; 1 8-KB bank CHR data (8KB total)        ;;
;;    .inesmap 0          ; No mapper                               ;;
;;    .inesmir 0          ; Vertical mirroring                      ;;
                                                                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	.ORG 0
	.BASE 0
	.DB "NES", $1A, 2, 1

;;;;;;;; + 2.0 VARIABLES + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                       ;;
;;     .rsset $0000        ; Start variables at $0000 (zero page)      ;;
;; music           .rs 16  ; Leave the first 16 bytes free for music   ;;
;; buttons1        .rs 1   ; Buttons pressed (P1)                      ;;
;; buttons1pending .rs 1   ; Buttons pressed but not read (P1)         ;;
;; buttons1read    .rs 1   ; Buttons pressed that need to be read (P1) ;;
;; framecounter    .rs 1   ; General-purpose frame counter             ;;
;; gamesetting     .rs 1   ; #@76543210                                ;;
;;                         ;   |||||||+ Glitching on (1) or off (0)    ;;
;;                         ;   ||||||+- Sparkles on (1) or off (0)     ;;
;;                         ;   ||||++-- Cycle through palettes:        ;;
;;                         ;   ||||     dark (00), pastel (01),        ;;
;;                         ;   ||||     default (10), or bright (11)   ;;
;;                         ;   |||+---- Color cycle on (1) or off (0)  ;;
;;                         ;   +++----- Not used                       ;;
;; oldgamesetting  .rs 1   ; Compare this against gamesetting to see   ;;
                        ; if updates are needed                        ;;
                                                                       ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	.ENUM 0

		music,            16  ; Leave the first 16 bytes free for music   ;;          
		buttons1,         1   ; Buttons pressed (P1)                      ;;      
		buttons1pending,  1   ; Buttons pressed but not read (P1)         ;;          
		buttons1read,     1   ; Buttons pressed that need to be read (P1) ;;      
		framecounter,     1   ; General-purpose frame counter             ;;    

		; #@76543210                                ;;      
		;   |||||||+ Glitching on (1) or off (0)    ;;
		;   ||||||+- Sparkles on (1) or off (0)     ;;
		;   ||||++-- Cycle through palettes:        ;;
		;   ||||     dark (00), pastel (01),        ;;
		;   ||||     default (10), or bright (11)   ;;
		;   |||+---- Color cycle on (1) or off (0)  ;;
		;   +++----- Not used                       ;;  
		gamesetting,      1

		; Compare this against gamesetting to see
		; if updates are needed
		oldgamesetting,   1   

	.ENDE

;;;;;;;; + 3.0 CONSTANTS + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
; INITADDR = $A999        ; Init address for music                  ;;
; LOADADDR = $A6E0        ; Load address for music                  ;;
; PLAYADDR = $A99C        ; Play address for music                  ;;
                                                                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

	.DEF INITADDR, $A999        ; Init address for music
	.DEF LOADADDR, $A6E0        ; Load address for music
	.DEF PLAYADDR, $A99C        ; Play address for music

;;;;;;;; + 4.0 GAME CODE: BANK 0 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
    ; .base $10           ; Bank 0                                    ;;
    .ORG $8000          ; begins at address $8000                   ;;
	.BASE $10
                                                                    ;;
;;;;;;;;;; 4.1 Console initialization ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
Reset:                  ; This code runs when console is reset      ;;
    SEI                                                             ;;
    CLD                                                             ;;
    LDX #$40                                                        ;;
    STX $4017                                                       ;;
    LDX #$FF                                                        ;;
    TXS                                                             ;;
    INX                                                             ;;
    STX $2000                                                       ;;
    STX $2001                                                       ;;
    STX $4010                                                       ;;
Vblank1:                ; Wait for first V-blank                    ;;
    BIT $2002                                                       ;;
    BPL Vblank1                                                     ;;
ClearMem:               ; Clear memory                              ;;                    
    LDA #$00                                                        ;;
    STA $0000,X                                                     ;;
    STA $0100,X                                                     ;;
    STA $0300,X                                                     ;;
    STA $0400,X                                                     ;;
    STA $0500,X                                                     ;;
    STA $0600,X                                                     ;;
    STA $0700,X                                                     ;;
    LDA #$FE                                                        ;;
    STA $0200,X                                                     ;;
    INX                                                             ;;
    BNE ClearMem                                                    ;;
Vblank2:                ; Wait for second V-blank                   ;;
    BIT $2002                                                       ;;
    BPL Vblank2                                                     ;; 
                                                                    ;;
;;;;;;;;; 4.2 Game initialization ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;  
    LDA #$00            ; Initialize sound registers                ;;
    LDX #$00                                                        ;;
ClearSoundLoop:                                                     ;;
    STA $4000,x                                                     ;;
    INX                                                             ;;
    CPX #$0F                                                        ;;  
    BNE ClearSoundLoop                                              ;;
    LDA #$10                                                        ;;
    STA $4010                                                       ;;
    LDA #$00                                                        ;;
    STA $4011                                                       ;;
    STA $4012                                                       ;;
    STA $4013                                                       ;;
    LDA #@00001111                                                  ;;
    STA $4015                                                       ;;  
    LDA #$00                                                        ;;
    LDX #$00                                                        ;;
    JSR INITADDR                                                    ;;
    LDA #$00            ; Reset framecounter                        ;;
    STA framecounter                                                ;;
    LDA #@00001000      ; Set default palette, disable glitching    ;;
                        ; and sparkles                              ;;
    STA gamesetting                                                 ;;
    STA oldgamesetting                                              ;;
    JSR TurnScreenOff   ; Disable screen rendering                  ;;
    JSR LoadBG          ; Load background                           ;;
    JSR LoadSpr         ; Load sprites                              ;;
    JSR TurnScreenOn    ; Enable screen rendering                   ;;
                                                                    ;;
;;;;;;;;;;;; 4.3 Game loop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
GameLoop:                                                           ;;
    JMP GameLoop        ; Infinite main game loop                   ;;
                                                                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;; + 5.0 GAME CODE: BANK 1 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
    ; .bank 1             ; Bank 1                                    ;;
    .org LOADADDR       ; Starts at music LOADADDR                  ;;
    .incbin "assets/music.nsf" ; Include binary NSF music file             ;;
                                                                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;; + 6.0 GAME CODE: BANK 2 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
    ; .bank 2             ; Bank 2                                    ;;
    .org $C000          ; Starts at memory address $C000            ;;
                                                                    ;;
;;;;;;;;;;;; 6.1 NMI ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
NMI:                    ; Non-maskable interrupt                    ;;
    PHA                 ; Back up registers                         ;;
    TXA                                                             ;;
    PHA                                                             ;;
    TYA                                                             ;;
    PHA                                                             ;;
    LDX framecounter    ; Add one to the frame counter              ;;
    INX                                                             ;;
    STX framecounter                                                ;;
    JSR SpriteDMA       ; Bring in sprite data (heart and sparkles) ;;
    LDA framecounter    ; Use the framecounter to delay frames      ;;
    AND #@00000011      ; in heart sprite animation                 ;;
    CMP #@00000011      ; When the framecounter hits #@xxxxxx11,    ;;                                          
    BEQ NMIAnimateHeart ; Go to the heart animation routine         ;;
    JMP NMISparkles     ; Otherwise, check if sparkles should be on ;;
NMIAnimateHeart:        ; Heart animation subroutine                ;;
    LDA $0301           ; Check if the first heart tile is $00      ;;
    BEQ NMIAnimateHeart2; If so, go to second-frame routine         ;;
NMIAnimateHeart1:       ; Otherwise, do the first-frame routine     ;;
    LDA #$00            ; The animated stripes on the heart are     ;;
    STA $0301           ; acheived by cycling through two sets of   ;;
    LDA #$01            ; heart tiles--this is the first set        ;;
    STA $0305                                                       ;;
    LDA #$10                                                        ;;
    STA $0309                                                       ;;
    LDA #$11                                                        ;;
    STA $030D                                                       ;;
    JMP NMIColorizeHeart; Jump to heart color cycling               ;;
NMIAnimateHeart2:       ; The second-frame routine                  ;;
    LDA #$02            ; The animated stripes on the heart are     ;;
    STA $0301           ; acheived by cycling through two sets of   ;;
    LDA #$03            ; heart tiles--this is the second set       ;;
    STA $0305                                                       ;;
    LDA #$12                                                        ;;
    STA $0309                                                       ;;
    LDA #$13                                                        ;;
    STA $030D                                                       ;;
NMIColorizeHeart:       ; Heart color-cycling subroutine            ;;
    LDA framecounter    ; Based on the framecounter value, the      ;;
    AND #@00001100      ; heart should be assigned different        ;;
    LSR                 ; attribute values to acheive the color     ;;
    LSR                 ; cycling effect                            ;;
    STA $0302                                                       ;;
    STA $0306                                                       ;;
    STA $030A                                                       ;;
    STA $030E                                                       ;;
    STA $0312                                                       ;;
    STA $0316                                                       ;;
    STA $031A                                                       ;;
    STA $031E                                                       ;;
NMISparkles:            ; Sparkles routine                          ;;
    JSR ReadController1 ; Read P1 controller                        ;;
    LDA buttons1read    ; If B is pressed                           ;;
    AND #@10000000                                                  ;;
    BNE NMISparkleCheck ; Go to "Sparkle toggle" routine            ;;
    LDA gamesetting     ; Otherwise, check gamesetting              ;;
    AND #@00000010      ; If sparkles are on, go to anim. routine   ;;
    BNE NMISparkleAnimate2                                          ;;
    JMP NMISparkleStop  ; If sparkles are off, keep 'em off         ;;
NMISparkleCheck:        ; "Sparkle toggle" subroutine               ;;
    LDA gamesetting     ; Turn sparkles on or off depending on      ;;
    AND #@00000010      ; "sparkle bit" of gamesetting (#@xxxxxx1x) ;;
    BNE NMISparkleStop  ; If they should be off, turn 'em off       ;;
NMISparkleAnimate:      ; Otherwise, turn 'em on                    ;;
    LDA gamesetting     ; Update gamesetting "sparkle bit"          ;;
    ORA #@00000010      ; (#@xxxxxx1x)                              ;;
    STA gamesetting                                                 ;;
    LDA #$04            ; Update sparkle tile frames                ;;
    STA $0311                                                       ;;
    LDA #$05                                                        ;;
    STA $0315                                                       ;;
    LDA #$14                                                        ;;
    STA $0319                                                       ;;
    LDA #$15                                                        ;;
    STA $031D                                                       ;;
NMISparkleAnimate2:     ; Update sparkle tile positions             ;;
    LDA $0310                                                       ;;
    SEC                                                             ;;
    SBC $0234           ; Note: $0234 is a value in RAM that        ;;
    STA $0310           ; corresponds to the melody playing on a    ;; 
    LDA $0313           ; square-wave channel, so adding or         ;;
    SEC                 ; subtracting this value from the sparkle   ;;
    SBC $0234           ; tiles' X- and Y-coordinates will create   ;;
    STA $0313           ; an audio visualizer effect                ;;
    LDA $0314                                                       ;;
    SEC                                                             ;;
    SBC $0234                                                       ;;
    STA $0314                                                       ;;
    LDA $0317                                                       ;;
    CLC                                                             ;;
    ADC $0234                                                       ;;
    STA $0317                                                       ;;
    LDA $0318                                                       ;;
    CLC                                                             ;;
    ADC $0234                                                       ;;
    STA $0318                                                       ;;
    LDA $031B                                                       ;;
    SEC                                                             ;;
    SBC $0234                                                       ;;
    STA $031B                                                       ;;
    LDA $031C                                                       ;;
    CLC                                                             ;;
    ADC $0234                                                       ;;
    STA $031C                                                       ;;
    LDA $031F                                                       ;;
    CLC                                                             ;;
    ADC $0234                                                       ;;
    STA $031F                                                       ;;
    JMP NMIColorSetting ; Sparkles are done, jump to palette updates;;
NMISparkleStop:         ; "Disable sparkles" routine                ;;
    LDA gamesetting     ; Update "sparkle bit" (#@xxxxxx1x) to      ;;
    AND #@11111101      ; reflect that sparkles are off             ;;
    STA gamesetting                                                 ;;
    LDA #$06            ; Load all sparkle tiles with a blank ($06) ;;
    STA $0311                                                       ;;
    STA $0315                                                       ;;
    STA $0319                                                       ;;
    STA $031D                                                       ;;
NMISparkleReset:        ; Reset motion cycle for sparkles           ;;
    LDA #$5C            ; Reset Y-positions for tiles               ;;
    STA $0310                                                       ;;
    STA $0314                                                       ;;
    STA $0318                                                       ;;
    STA $031C                                                       ;;
    LDA #$7B            ; Reset X-positions for tiles               ;;
    STA $0313                                                       ;;
    STA $0317                                                       ;;
    STA $031B                                                       ;;
    STA $031F                                                       ;;
NMIColorSetting:        ; Check color palette setting               ;;
    LDA buttons1read    ; If up is pressed                          ;;
    AND #@00001100                                                  ;;
    CMP #@00001000                                                  ;;
    BEQ NMIColorInc     ; Go to "Make colors darker" routine        ;;
    CMP #@00000100      ; If down is pressed                        ;;
    BEQ NMIColorDec     ; Go to "Make colors lighter" routine       ;;
    JMP NMIGlitch       ; Otherwise, go to glitch updates           ;;
NMIColorInc:            ; "Make colors darker" routine              ;;
    LDA gamesetting     ; If colors are at darkest setting already, ;;
    AND #@00001100                                                  ;;
    BEQ NMIGlitch       ; We're done here, skip to glitch updates   ;;
    CMP #@00001000      ; If color bits are set to Default,         ;;
    BEQ NMIColorBright  ; Go to "Make it Bright" routine            ;;
    CMP #@00000100      ; If color bits are set to Pastel,          ;;
    BEQ NMIColorDefault ; Go to "Make it Default" routine           ;;
    JMP NMIColorDark    ; Otherwise, go to "Make it Dark" routine   ;;
NMIColorDec:            ; "Make colors lighter" routine             ;;
    LDA gamesetting     ; If colors are at lightest setting already,;;
    AND #@00001100                                                  ;;
    CMP #@00000100                                                  ;;
    BEQ NMIGlitch       ; We're done here, skip to glitch updates   ;;
    CMP #@00001100      ; If color bits are set to Bright,          ;;
    BEQ NMIColorDefault ; Go to "Make it Default" routine           ;;
    CMP #@00001000      ; If color bits are set to Default,         ;;
    BEQ NMIColorPastel  ; Go to "Make it Pastel" routine            ;;
    JMP NMIColorBright  ; Else, go to "Make it Bright" routine      ;;
NMIColorDefault:        ; "Make it Default" subroutine              ;;
    JSR LoadDefaultPal  ; Do "Load Default palette" subroutine      ;;
    LDA gamesetting     ; Update color bits to reflect new palette  ;;
    ORA #@00001000                                                  ;;
    AND #@11111011                                                  ;;
    STA gamesetting                                                 ;;
    JMP NMIGlitch       ; Skip to glitch updates                    ;;
NMIColorDark:           ; "Make it Dark" routine                    ;;
    JSR LoadDarkPal     ; Do "Load Dark palette" subroutine         ;;
    LDA gamesetting     ; Update color bits to reflect new palette  ;;
    AND #@11110011                                                  ;;
    STA gamesetting                                                 ;;
    JMP NMIGlitch       ; Skip to glitch updates                    ;;
NMIColorBright:         ; "Make it Bright" routine                  ;;
    JSR LoadBrightPal   ; Do "Load Bright palette" subroutine       ;;
    LDA gamesetting     ; Update color bits to reflect new palette  ;;
    ORA #@00001100                                                  ;;
    STA gamesetting                                                 ;;
    JMP NMIGlitch       ; Skip to glitch updates                    ;;
NMIColorPastel:         ; "Make it Pastel" routine                  ;;
    JSR LoadPastelPal   ; Do "Load Pastel palette" subroutine       ;;
    LDA gamesetting     ; Update color bits to reflect new palette  ;;
    ORA #@00000100                                                  ;;
    AND #@11110111                                                  ;;
    STA gamesetting                                                 ;;
NMIGlitch:              ; Check whether screen should be glitching  ;;
    LDA #$00            ; Disable scrolling                         ;;
    STA $2005                                                       ;;
    STA $2005                                                       ;;
    JSR TurnScreenOn    ; Turn on screen rendering                  ;;
    LDA buttons1read    ; If A is pressed                           ;;
    AND #@01000000      ; Go to "Glitch toggle" routine             ;;
    BNE NMICheckForGlitch                                           ;;
    LDA gamesetting     ; If "glitch bit" (#@xxxxxxx1) is on,       ;;
    AND #@00000001                                                  ;;
    BNE NMIGlitch2      ; Go get glitchy                            ;;
    JMP NMIDone         ; Otherwise, jump to end of NMI routine     ;;
NMICheckForGlitch:      ; "Glitch toggle" routine                   ;;
    LDA gamesetting     ; Check gamesetting "glitch bit"            ;;
    AND #@00000001      ; If it's off,                              ;;
    CMP #@00000001                                                  ;;
    BEQ NMINoGlitch     ; Don't glitch                              ;;
NMIGlitch2:             ; Otherwise, get glitchy                    ;;
    LDA framecounter    ; Load value in framecounter                ;;
    STA $2006           ; Throw it in graphics registers            ;;
    STA $2007           ; (When this is done with rendering on,     ;;
    STA $2007           ; things get glitchy)                       ;;
    LDA gamesetting     ; Set "glitch bit" to on                    ;;
    ORA #@00000001                                                  ;;
    STA gamesetting                                                 ;;
    JMP NMIDone         ; Finish up NMI routine                     ;;
NMINoGlitch:            ; "Don't glitch" routine                    ;;
    LDA gamesetting     ; Set "glitch bit" to off                   ;;
    AND #@11111110                                                  ;;
    STA gamesetting                                                 ;;
NMIDone:                ; Final actions in NMI                      ;;
    JSR PLAYADDR        ; Update audio                              ;;
    PLA                 ; Restore registers                         ;;
    TAY                                                             ;;
    PLA                                                             ;;
    TAX                                                             ;;
    PLA                                                             ;;
    RTI                 ; NMI is done                               ;;
                                                                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
;;;;;;;;;;;; 6.2 Subroutines ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
SpriteDMA:              ; Sprite DMA subroutine                     ;;
    LDA #$00                                                        ;;
    STA $2003                                                       ;;
    LDA #$03                                                        ;;
    STA $4014                                                       ;;
    RTS                                                             ;;
LoadDefaultPal:         ; "Load Default palette" subroutine         ;;
    LDA $2002                                                       ;;
    LDA #$3F                                                        ;;
    STA $2006                                                       ;;
    LDA #$00                                                        ;;
    STA $2006                                                       ;;
    LDX #$00                                                        ;;
LoadDefaultPalLoop:                                                 ;;
    LDA defaultpal,X                                                ;;
    STA $2007                                                       ;;
    INX                                                             ;;
    CPX #$20                                                        ;;
    BNE LoadDefaultPalLoop                                          ;;
    RTS                                                             ;;
LoadDarkPal:            ; "Load Dark palette" subroutine            ;;
    LDA $2002                                                       ;;
    LDA #$3F                                                        ;;
    STA $2006                                                       ;;
    LDA #$00                                                        ;;
    STA $2006                                                       ;;
    LDX #$00                                                        ;;
LoadDarkPalLoop:                                                    ;;
    LDA darkpal,X                                                   ;;
    STA $2007                                                       ;;
    INX                                                             ;;
    CPX #$20                                                        ;;
    BNE LoadDarkPalLoop                                             ;;
    RTS                                                             ;;
LoadBrightPal:          ; "Load Bright palette" subroutine          ;;
    LDA $2002                                                       ;;
    LDA #$3F                                                        ;;
    STA $2006                                                       ;;
    LDA #$00                                                        ;;
    STA $2006                                                       ;;
    LDX #$00                                                        ;;
LoadBrightPalLoop:                                                  ;;
    LDA brightpal,X                                                 ;;
    STA $2007                                                       ;;
    INX                                                             ;;
    CPX #$20                                                        ;;
    BNE LoadBrightPalLoop                                           ;;
    RTS                                                             ;;
LoadPastelPal:          ; "Load Pastel palette" subroutine          ;;
    LDA $2002                                                       ;;
    LDA #$3F                                                        ;;
    STA $2006                                                       ;;
    LDA #$00                                                        ;;
    STA $2006                                                       ;;
    LDX #$00                                                        ;;
LoadPastelPalLoop:                                                  ;;
    LDA pastelpal,X                                                 ;;
    STA $2007                                                       ;;
    INX                                                             ;;
    CPX #$20                                                        ;;
    BNE LoadPastelPalLoop                                           ;;
    RTS                                                             ;;
LoadBG:                 ; "Load background" subroutine              ;;
    LDA $2002                                                       ;;
    LDA #$3F                                                        ;;
    STA $2006                                                       ;;
    LDA #$00                                                        ;;
    STA $2006                                                       ;;
    LDX #$00                                                        ;;
LoadPalLoop:            ; Default palette is loaded on reset        ;;
    LDA defaultpal,X                                                ;;
    STA $2007                                                       ;;
    INX                                                             ;;
    CPX #$20                                                        ;;
    BNE LoadPalLoop                                                 ;;
    LDA $2002                                                       ;;
    LDA #$20                                                        ;;
    STA $2006                                                       ;;
    LDA #$00                                                        ;;
    STA $2006                                                       ;;
    LDX #$00                                                        ;;
LoadTitleNewNam1:       ; Load first set of 256 background tiles    ;;
    LDA background1,x                                               ;;
    STA $2007                                                       ;;
    INX                                                             ;;
    BNE LoadTitleNewNam1                                            ;;
LoadTitleNewNam2:       ; Load second set of 256 background tiles   ;;
    LDA background2,x                                               ;;
    STA $2007                                                       ;;
    INX                                                             ;;
    BNE LoadTitleNewNam2                                            ;;
LoadTitleNewNam3:       ; Load third set of 256 background tiles    ;;
    LDA background3,x                                               ;;
    STA $2007                                                       ;;
    INX                                                             ;;
    BNE LoadTitleNewNam3                                            ;;
LoadTitleNewNam4:       ; Load fourth set of background tiles       ;;
    LDA background4,x                                               ;;
    STA $2007                                                       ;;
    INX                                                             ;;
    CPX #$E0            ; (Don't have to load all 256)              ;;
    BNE LoadTitleNewNam4                                            ;;
LoadAttr:               ; Load initial attribute values for BG      ;;
    LDA #$23                                                        ;;
    STA $2006                                                       ;;
    LDA #$c0                                                        ;;
    STA $2006                                                       ;;
    LDX #$00                                                        ;;
LoadAttrLoop:                                                       ;;
    LDA attr,X                                                      ;;
    STA $2007                                                       ;;
    INX                                                             ;;
    CPX #$40                                                        ;;
    BNE LoadAttrLoop                                                ;;
    RTS                                                             ;;
LoadSpr:                ; Load initial sprite values                ;;
    LDX #$00                                                        ;;
LoadSprLoop:                                                        ;;
    LDA heart,x                                                     ;;
    STA $0300,x                                                     ;;
    INX                                                             ;;
    CPX #$20                                                        ;;
    BNE LoadSprLoop                                                 ;;
    RTS                                                             ;;
TurnScreenOn:           ; Enable screen rendering                   ;;
    LDA #@10010000                                                  ;;
    STA $2000                                                       ;;
    LDA #@00011010                                                  ;;
    STA $2001                                                       ;;
    RTS                                                             ;;
TurnScreenOff:          ; Disable screen rendering                  ;;
    LDA #$00                                                        ;;
    STA $2000                                                       ;;
    STA $2001                                                       ;;
    RTS                                                             ;;
ReadController1:        ; Read the P1 controller                    ;;
    LDA #$01                                                        ;;          
    STA $4016                                                       ;;
    LDA #$00                                                        ;;
    STA $4016                                                       ;;
    LDX #$08                                                        ;;
ReadController1Loop:                                                ;;
    LDA $4016                                                       ;;
    LSR                                                             ;;
    ROL buttons1                                                    ;;
    DEX                                                             ;;
    BNE ReadController1Loop                                         ;;
    LDA buttons1pending ; Note: This code is helpful in helping to  ;;
    EOR #@11111111      ; distinguish between reading a continuous  ;;                                          
    AND buttons1        ; button press and a single button press    ;;
    STA buttons1read    ; Often, we want to read the first button   ;;
    LDA buttons1        ; value sent and then ignore subsequent     ;;
    STA buttons1pending ; reads until the button is released        ;;
    RTS                                                             ;;
                                                                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
;;;;;;;;;;;; 6.3 Binary data ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
background1:            ; First 256-tile set of background          ;;
    .INCBIN "assets/background1.bin"                                ;;
background2:            ; Second 256-tile set of background         ;;
    .INCBIN "assets/background2.bin"                                ;;
background3:            ; Third 256-tile set of background          ;;
    .INCBIN "assets/background3.bin"                                ;;
background4:            ; Fourth 256-tile set of background         ;;
    .INCBIN "assets/background4.bin"                                ;;
defaultpal:             ; Default color palette                     ;;
    .db $38,$30,$26,$25 ; Background colors                         ;;
    .db $38,$30,$2B,$21                                             ;;
    .db $38,$30,$23,$21                                             ;;
    .db $38,$30,$30,$30                                             ;;
    .db $38,$23,$22,$21 ; Sprite colors                             ;;
    .db $38,$2C,$2B,$2A                                             ;;
    .db $38,$29,$28,$27                                             ;;
    .db $38,$26,$25,$24                                             ;;
darkpal:                ; Dark color palette                        ;;
    .db $18,$30,$06,$05 ; Background colors                         ;;
    .db $18,$30,$0B,$01                                             ;;
    .db $18,$30,$03,$01                                             ;;
    .db $18,$30,$30,$30                                             ;;
    .db $18,$03,$02,$01 ; Sprite colors                             ;;
    .db $18,$0C,$0B,$0A                                             ;;
    .db $18,$09,$08,$07                                             ;;
    .db $18,$06,$05,$04                                             ;;
brightpal:              ; Bright color palette                      ;;
    .db $28,$30,$16,$15 ; Background colors                         ;;
    .db $28,$30,$1B,$11                                             ;;
    .db $28,$30,$13,$11                                             ;;
    .db $28,$30,$30,$30                                             ;;
    .db $28,$13,$12,$11 ; Sprite colors                             ;;
    .db $28,$1C,$1B,$1A                                             ;;
    .db $28,$19,$18,$17                                             ;;
    .db $28,$16,$15,$14                                             ;;
pastelpal:              ; Pastel color palette                      ;;
    .db $37,$30,$36,$35 ; Background colors                         ;;
    .db $37,$30,$3B,$31                                             ;;
    .db $37,$30,$33,$31                                             ;;
    .db $37,$30,$30,$30                                             ;;
    .db $37,$33,$32,$31 ; Sprite colors                             ;;
    .db $37,$3C,$3B,$3A                                             ;;
    .db $37,$39,$38,$37                                             ;;
    .db $37,$36,$35,$34                                             ;;
attr:                   ; Color attribute table                     ;;
    .db $00,$00,$00,$00,$00,$00,$00,$00                             ;;
    .db $00,$00,$00,$00,$00,$00,$00,$00                             ;;
    .db $50,$50,$50,$50,$50,$50,$50,$50                             ;;
    .db $56,$56,$56,$56,$56,$56,$56,$56                             ;;
    .db $55,$55,$55,$55,$55,$55,$55,$55                             ;;
    .db $A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5                             ;;
    .db $AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA                             ;;
    .db $0A,$0A,$0A,$0A,$0A,$0A,$AA,$AA                             ;;
heart:                  ; Heart and sparkle sprite tile data        ;;
    .db $58,$00,$00,$78 ; Heart tiles                               ;;
    .db $58,$01,$00,$80                                             ;;
    .db $60,$10,$00,$78                                             ;;
    .db $60,$11,$00,$80                                             ;;
    .db $5C,$04,$00,$7C ; Sparkle tiles                             ;;  
    .db $5C,$05,$00,$7C                                             ;;
    .db $5C,$14,$00,$7C                                             ;;
    .db $5C,$15,$00,$7C                                             ;;
                                                                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    

;;;;;;;; + 7.0 GAME CODE: BANK 2 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
    ; .bank 3             ; Bank 3                                  ;;
    .org $E000          ; Begins at memory address $E000            ;;
    .org $FFFA          ; Final three bytes (vectors):              ;;
    .dw NMI             ; When an NMI happens, jump to NMI          ;;
    .dw Reset           ; On reset/power on, jump to Reset          ;;
    .dw 0               ; IRQ disabled                              ;;
                                                                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
  
;;;;;;;; + 8.0 GRAPHICS DATA: BANK 4 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                                                                    ;;
    ; .bank 4             ; Bank 4                                  ;;
    ; .org $0000          ; Starts at $0000 (CHR)                   ;;
    .incbin "assets/gfx.bin"   ; Include graphics binary            ;;
                                                                    ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
